package ast

import (
	"bytes"
	"monkey/token"
	"strings"
)

// Node 节点接口
type Node interface {
	TokenLiteral() string
	String() string
}

// Statement 语句接口
// 语句有let语句，return语句，块语句，表达式语句
// let语句类似let x = 5;
// return语句类似return x;
// 块语句类似{let x = 5; return x;}
// 表达式语句类似x;，5;
type Statement interface {
	Node
	statementNode()
}

// Expression 表达式接口
type Expression interface {
	Node
	expressionNode()
}

// Program 程序结构体
// 一个Program是由多个Statement语句构成的
// Program结构体实现Node接口，可以看成是词法树的根节点
type Program struct {
	Statements []Statement
}

// TokenLiteral 实现TokenLiteral方法
func (p *Program) TokenLiteral() string {
	if len(p.Statements) > 0 {
		return p.Statements[0].TokenLiteral()
	}
	return ""
}

// 实现String方法
func (p *Program) String() string {
	var out bytes.Buffer
	for _, s := range p.Statements {
		out.WriteString(s.String())
	}
	return out.String()
}

// Identifier 标识符节点，实现Expression接口，可以看成是表达式，标识符可以看成是变量，单个变量是表达式
type Identifier struct {
	Token token.Token
	Value string
}

// 实现Expression的方法
func (i *Identifier) expressionNode() {

}

// TokenLiteral 实现Expression的方法
func (i *Identifier) TokenLiteral() string {
	return i.Token.Literal
}

// 实现Expression的方法
func (i *Identifier) String() string {
	return i.Value
}

// LetStatement let语句，实现Statement接口
type LetStatement struct {
	// 字面值 let
	Token token.Token
	// 标识符
	Name *Identifier
	// 表达式
	// 注意：标识符也是表达式
	Value Expression
}

// 实现Statement接口的方法
func (ls *LetStatement) statementNode() {

}

func (ls *LetStatement) TokenLiteral() string {
	return ls.Token.Literal
}

func (ls *LetStatement) String() string {
	var out bytes.Buffer
	out.WriteString(ls.TokenLiteral() + " ")
	out.WriteString(ls.Name.String())
	out.WriteString(" = ")

	if ls.Value != nil {
		out.WriteString(ls.Value.String())
	}

	out.WriteString(";")
	return out.String()
}

// ReturnStatement return语句，实现Statement接口
type ReturnStatement struct {
	// 字面值 return
	Token token.Token
	// 表达式
	ReturnValue Expression
}

// 实现Statement接口的方法
func (rs *ReturnStatement) statementNode() {

}

func (rs *ReturnStatement) TokenLiteral() string {
	return rs.Token.Literal
}

func (rs *ReturnStatement) String() string {
	var out bytes.Buffer
	out.WriteString(rs.TokenLiteral() + " ")

	if rs.ReturnValue != nil {
		out.WriteString(rs.ReturnValue.String())
	}

	out.WriteString(";")
	return out.String()
}

// ExpressionStatement 表达式语句，实现Statement接口
type ExpressionStatement struct {
	// 表达式的第一个token
	Token      token.Token
	Expression Expression
}

// 实现Statement接口的方法
func (es *ExpressionStatement) statementNode() {

}

func (es *ExpressionStatement) TokenLiteral() string {
	return es.Token.Literal
}

func (es *ExpressionStatement) String() string {
	if es.Expression != nil {
		return es.Expression.String()
	}
	return ""
}

// BlockStatement 块语句，实现Statement接口，比如if语句的块语句和函数的块语句
type BlockStatement struct {
	// {
	Token      token.Token
	Statements []Statement
}

// 实现Statement接口的方法
func (bs *BlockStatement) statementNode() {

}

func (bs *BlockStatement) TokenLiteral() string {
	return bs.Token.Literal
}

func (bs *BlockStatement) String() string {
	var out bytes.Buffer
	for _, s := range bs.Statements {
		out.WriteString(s.String())
	}
	return out.String()
}

// Boolean bool值，实现Expression接口
type Boolean struct {
	// true或false的字面值
	Token token.Token
	// 存储的实际的bool值
	Value bool
}

// 实现Expression接口的方法
func (b *Boolean) expressionNode() {

}

func (b *Boolean) TokenLiteral() string {
	return b.Token.Literal
}

func (b *Boolean) String() string {
	return b.Token.Literal
}

// IntegerLiteral 整数值，实现Expression接口
type IntegerLiteral struct {
	// 数字的第一个字符
	Token token.Token
	// 整数
	Value int64
}

// 实现Expression接口的方法
func (il *IntegerLiteral) expressionNode() {

}

func (il *IntegerLiteral) TokenLiteral() string {
	return il.Token.Literal
}

func (il *IntegerLiteral) String() string {
	return il.Token.Literal
}

// PrefixExpression 前缀表达式，实现Expression接口
type PrefixExpression struct {
	// 前缀符，有：-，!，
	Token token.Token
	// 前缀操作符，
	Operator string
	// 前缀操作符的右边，是一个表达式
	Right Expression
}

// 实现Expression接口的方法
func (pe *PrefixExpression) expressionNode() {

}

func (pe *PrefixExpression) TokenLiteral() string {
	return pe.Token.Literal
}

func (pe *PrefixExpression) String() string {
	var out bytes.Buffer
	out.WriteString("(")
	out.WriteString(pe.Operator)
	out.WriteString(pe.Right.String())
	out.WriteString(")")
	return out.String()
}

// InfixExpression 中缀表达式，实现Expression接口
type InfixExpression struct {
	// 中缀符，有+，-，*，/
	Token token.Token
	// 中缀符左边的表达式
	Left Expression
	// 中缀符
	Operator string
	// 中缀符右边的表达式
	Right Expression
}

// 实现Expression接口的方法
func (ie *InfixExpression) expressionNode() {

}

func (ie *InfixExpression) TokenLiteral() string {
	return ie.Token.Literal
}

func (ie *InfixExpression) String() string {
	var out bytes.Buffer

	out.WriteString("(")
	out.WriteString(ie.Left.String())
	out.WriteString(" " + ie.Operator + " ")
	out.WriteString(ie.Right.String())
	out.WriteString(")")

	return out.String()
}

// IfExpression if表达式
// 注意：现在不支持else if
type IfExpression struct {
	// 字面值i
	Token token.Token
	// if的条件表达式
	Condition Expression
	// 条件表达式正确时执行的语句，是块语句，实现了Statement接口
	Consequence *BlockStatement
	// 条件表达式不正确时执行的语句，是块语句，实现了Statement接口
	Alternative *BlockStatement
}

// 实现Expression接口的方法
func (ie *IfExpression) expressionNode() {

}

func (ie *IfExpression) TokenLiteral() string {
	return ie.Token.Literal
}

func (ie *IfExpression) String() string {
	var out bytes.Buffer

	out.WriteString("if")
	out.WriteString(ie.Condition.String())
	out.WriteString(" ")
	out.WriteString(ie.Consequence.String())

	if ie.Alternative != nil {
		out.WriteString("else ")
		out.WriteString(ie.Alternative.String())
	}
	return out.String()
}

// FunctionLiteral 函数，fn()，实现了Expression接口
// 注意：现在的函数是表达式，可以赋值给标识符，也可以在另外的函数中返回
type FunctionLiteral struct {
	// f字面值
	Token token.Token
	// 函数的参数，函数的参数是标识符，可以有0到多个
	Parameters []*Identifier
	// 函数体，是块语句，实现了Statement接口
	Body *BlockStatement
}

// 实现Expression接口
func (fl *FunctionLiteral) expressionNode() {

}

func (fl *FunctionLiteral) TokenLiteral() string {
	return fl.Token.Literal
}

func (fl *FunctionLiteral) String() string {
	var out bytes.Buffer

	params := []string{}
	for _, p := range fl.Parameters {
		params = append(params, p.String())
	}

	out.WriteString(fl.TokenLiteral())
	out.WriteString("(")
	out.WriteString(strings.Join(params, ", "))
	out.WriteString(")")
	out.WriteString(fl.Body.String())

	return out.String()
}

// CallExpression 调用函数，实现了Expression接口，调用函数是可以返回表达式的，所以CallExpression是表达式
type CallExpression struct {
	// 标识符，标识符指向的函数的定义
	Token token.Token
	// 函数标识符
	Function Expression
	// 函数的参数
	Arguments []Expression
}

// 实现Expression接口的方法
func (ce *CallExpression) expressionNode() {

}

func (ce *CallExpression) TokenLiteral() string {
	return ce.Token.Literal
}

func (ce *CallExpression) String() string {
	var out bytes.Buffer

	args := []string{}
	for _, a := range ce.Arguments {
		args = append(args, a.String())
	}

	out.WriteString(ce.Function.String())
	out.WriteString("(")
	out.WriteString(strings.Join(args, ", "))
	out.WriteString(")")

	return out.String()
}

// StringLiteral 字符串
type StringLiteral struct {
	Token token.Token
	Value string
}

// 实现Expression接口的方法
func (sl *StringLiteral) expressionNode() {

}

func (sl *StringLiteral) TokenLiteral() string {
	return sl.Token.Literal
}

func (sl *StringLiteral) String() string {
	return sl.Token.Literal
}

// ArrayLiteral 数组
type ArrayLiteral struct {
	Token    token.Token
	Elements []Expression
}

// 实现Expression接口的方法
func (al *ArrayLiteral) expressionNode() {

}

func (al *ArrayLiteral) TokenLiteral() string {
	return al.Token.Literal
}

func (al *ArrayLiteral) String() string {
	var out bytes.Buffer
	elements := []string{}
	for _, al := range al.Elements {
		elements = append(elements, al.String())
	}

	out.WriteString("[")
	out.WriteString(strings.Join(elements, ","))
	out.WriteString("]")

	return out.String()
}

// IndexExpression index表达式
type IndexExpression struct {
	// [
	Token token.Token
	// 数组
	Left Expression
	// 必须是integer
	Index Expression
}

// 实现Expression接口的方法
func (ie *IndexExpression) expressionNode() {

}

func (ie *IndexExpression) TokenLiteral() string {
	return ie.Token.Literal
}

func (ie *IndexExpression) String() string {
	var out bytes.Buffer

	out.WriteString("(")
	out.WriteString(ie.Left.String())
	out.WriteString("[")
	out.WriteString(ie.Index.String())
	out.WriteString("])")

	return out.String()
}

type HashLiteral struct {
	Token token.Token
	Pairs map[Expression]Expression
}

// 实现Expression接口的方法
func (hl *HashLiteral) expressionNode() {

}

func (hl *HashLiteral) TokenLiteral() string {
	return hl.Token.Literal
}

func (hl *HashLiteral) String() string {
	var out bytes.Buffer

	pairs := []string{}
	for key, value := range hl.Pairs {
		pairs = append(pairs, key.String()+":"+value.String())
	}

	out.WriteString("{")
	out.WriteString(strings.Join(pairs, ", "))
	out.WriteString("}")

	return out.String()
}
